home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / phone / ph_io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-02-01  |  10.1 KB  |  356 lines

  1. #include "util.h"
  2. #include "mmdf.h"
  3. #include "d_returns.h"
  4. /*
  5.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  6.  *     
  7.  *
  8.  *     Copyright (C) 1979,1980,1981  University of Delaware
  9.  *     
  10.  *     Department of Electrical Engineering
  11.  *     University of Delaware
  12.  *     Newark, Delaware  19711
  13.  *
  14.  *     Phone:  (302) 738-1163
  15.  *     
  16.  *     
  17.  *     This program module was developed as part of the University
  18.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  19.  *     
  20.  *     Acquisition, use, and distribution of this module and its listings
  21.  *     are subject restricted to the terms of a license agreement.
  22.  *     Documents describing systems using this module must cite its source.
  23.  *
  24.  *     The above statements must be retained with all copies of this
  25.  *     program and may not be removed without the consent of the
  26.  *     University of Delaware.
  27.  *     
  28.  *
  29.  *     version  -1    David H. Crocker    March   1979
  30.  *     version   0    David H. Crocker    April   1980
  31.  *     version  v7    David H. Crocker    May     1981
  32.  *     version   1    David H. Crocker    October 1981
  33.  *
  34.  */
  35. /*#define RUNALON   */
  36.  
  37. /*                  Handle telephone-based i/o                          */
  38.  
  39. extern struct ll_struct   *logptr;
  40. extern int    d_errno;              /* dial package error                 */
  41. extern char *blt ();
  42.  
  43. /*  NOTE:  load initialization routines from ph_iouser or ph_ioslave    */
  44.  
  45. /*   ************  (ph_)  PHONE MAIL I/O SUB-MODULE  ****************** */
  46.  
  47. ph_wrply (valstr, len)           /* pass a reply to local process      */
  48. struct rp_bufstruct *valstr;      /* string describing reply            */
  49. int       len;                      /* length of the string               */
  50. {
  51.     char    rp_string[LINESIZE];
  52.  
  53. #ifdef DEBUG
  54.     ll_log (logptr, LLOGBTR, "ph_wrply()");
  55.     ll_log (logptr, LLOGFTR, "(%s)'%s'",
  56.         rp_valstr (valstr -> rp_val), valstr -> rp_line);
  57. #endif
  58.                   /* turn rp code into two hex bytes    */
  59.                   /*   to avoid using high bit on phone */
  60.     rp_string[0] = d_tohex ((valstr -> rp_val >> 4) & 017);
  61.                   /* high four bits                     */
  62.     rp_string[1] = d_tohex (valstr -> rp_val & 017);
  63.                   /* low four bits                      */
  64.     blt (valstr -> rp_line, &rp_string[2], len);
  65.     return (ph_wrec (rp_string, len + 1));
  66. }
  67. /* */
  68.  
  69. ph_rrply (valstr, len)           /* get a reply from remote process    */
  70. struct rp_bufstruct *valstr;      /* where to stuff copy of reply text  */
  71. int      *len;                      /* where to indicate text's length    */
  72. {
  73.     short     retval;
  74.     char   *rplystr;
  75.     char    rp_string[LINESIZE];
  76.  
  77. #ifdef DEBUG
  78.     ll_log (logptr, LLOGBTR, "ph_rrply()");
  79. #endif
  80.  
  81.     retval = ph_rrec (
  82. #ifdef RUNALON
  83.         (char  *) valstr,
  84. #else
  85.             rp_string,
  86. #endif
  87.             len);
  88.     if (rp_gval (retval) != RP_OK)
  89.     return (retval);
  90.  
  91. #ifdef RUNALON
  92.     switch (rp_gval (valstr -> rp_val))
  93.     {
  94.     case 'd': 
  95.         valstr -> rp_val = RP_DONE;
  96.         break;
  97.     case 'y': 
  98.         valstr -> rp_val = RP_OK;
  99.         break;
  100.     case 'm': 
  101.         valstr -> rp_val = RP_MOK;
  102.         break;
  103.     case 'a': 
  104.         valstr -> rp_val = RP_AOK;
  105.         break;
  106.     case 'n': 
  107.         valstr -> rp_val = RP_NO;
  108.         break;
  109.     }
  110. #else
  111.     valstr -> rp_val = ((d_fromhex (rp_string[0]) & 017) << 4) |
  112.     (d_fromhex (rp_string[1]) & 017);
  113.     *len -= 1;              /* reply is shorter                   */
  114.     blt (&rp_string[2], valstr -> rp_line, *len);
  115.                   /* copy string + its null ending      */
  116. #endif
  117.  
  118.     rplystr = rp_valstr (valstr -> rp_val);
  119.     if (*rplystr == '*')
  120.     {                  /* replyer did a no-no                */
  121.     ll_log (logptr, LLOGTMP, "ILLEGAL REPLY: (%s)", rplystr);
  122.     valstr -> rp_val = RP_RPLY;
  123.     }
  124. #ifdef DEBUG
  125.     else
  126.     ll_log (logptr, LLOGFTR, "(%s)'%s'", rplystr, valstr -> rp_line);
  127. #endif
  128.  
  129.     return (RP_OK);
  130. }
  131. /*                 READ FROM REMOTE MAIL PROCESS                    */
  132.  
  133. ph_rrec (linebuf, len)           /* read one "record"                    */
  134. char   *linebuf;          /* where to stuff the text              */
  135. int      *len;                      /* where to stuff the length count      */
  136. {
  137.     short     retval;
  138.     int       goteot;               /* completed packet                   */
  139.  
  140. #ifdef DEBUG
  141.     ll_log (logptr, LLOGBTR, "ph_rrec ()");
  142. #endif
  143.  
  144. #ifdef RUNALON
  145.     *len = read (0, linebuf, LINESIZE - 1);
  146.     *len -= 1;
  147. #else
  148.     if ((*len = d_rcvdata (linebuf, LINESIZE - 1, &goteot)) < 0)
  149.     {
  150.     retval = ph_d2rpval (*len);
  151.     ll_log (logptr, LLOGTMP,
  152.         "ph_rrec:  d_rcvdata err (%s)", rp_valstr (retval));
  153.     return (retval);
  154.     }
  155. #endif
  156.  
  157.     if (*len == 0)
  158.     {
  159.     ll_log (logptr, LLOGFTR, "zero len read");
  160.     return (RP_DONE);
  161.     }
  162.     linebuf[*len] = '\0';      /* keep things null-terminated        */
  163.  
  164.     if (!goteot)          /* packet is too long                 */
  165.     ll_log (logptr, LLOGFTR, "*** oversized packet");
  166.                   /* let is slip, for now               */
  167.  
  168. #ifdef DEBUG
  169.     ll_log (logptr, LLOGFTR, "(%d)'%s'", *len, linebuf);
  170. #endif
  171.     return (RP_OK);
  172. }
  173. /* */
  174.  
  175. ph_rstm (buffer, len)            /* read buffered block of text        */
  176. char   *buffer;              /* where to stuff the text            */
  177. int      *len;                      /* where to stuff count               */
  178. {
  179.     static int    goteos;           /* save end-of-stream across calls    */
  180.  
  181. #ifdef DEBUG
  182.     ll_log (logptr, LLOGBTR, "ph_rstm ()");
  183. #endif
  184.  
  185.     if (goteos)              /* was set automatically by dial      */
  186.     {
  187. #ifdef DEBUG
  188.     ll_log (logptr, LLOGFTR, "returning DONE");
  189. #endif
  190.     goteos = FALSE;
  191.     *buffer = '\0';
  192.     *len = 0;
  193.     return (RP_DONE);
  194.     }
  195.  
  196. #ifdef RUNALON
  197.     printx ("dm_rstm: ");
  198.  
  199.     *len = read (0, buffer, *len - 1);
  200.     if (*len == 0)
  201.     goteos = TRUE;
  202. #else
  203.     *len = d_rcvdata (buffer, *len - 1, &goteos);
  204. #endif
  205.  
  206.     if (*len < 0)
  207.     {
  208.     ll_log (logptr, LLOGGEN, "rdstm: error rcvdata");
  209.     return (ph_d2rpval (*len));
  210.     }
  211.     buffer[*len] = '\0';
  212.  
  213. #ifdef DEBUG
  214.     ll_log (logptr, LLOGFTR, "(%d)'%s'", *len, buffer);
  215. #endif
  216.     return (RP_OK);
  217. }
  218. /*                 WRITE TO REMOTE MAIL PROCESS                        */
  219.  
  220. ph_wrec (linebuf, len)           /* write a record/packet              */
  221. char    *linebuf;          /* chars to write                     */
  222. int    len;                      /* number of chars to write           */
  223. {
  224.     short     retval;
  225.  
  226. #ifdef DEBUG
  227.     ll_log (logptr, LLOGBTR, "ph_wrec () (%d)'%s'", len, linebuf ? linebuf : "");
  228. #endif
  229.  
  230. #ifdef RUNALON
  231.     if (linebuf == 0 && len == 0)
  232.     {
  233.     printf ("p_wrec (eof)\n");
  234.     fflush (stdout);
  235.     return (RP_OK);
  236.     }
  237.     if (write (1, linebuf, len) != len)
  238.     return (RP_DHST);
  239.     write (1, "\n", 1);          /* make it pretty */
  240.     return (RP_OK);
  241. #endif
  242.  
  243.     if ((retval = d_snstream (linebuf, len)) < D_OK ||
  244.         (retval = d_sneot ()) < D_OK)
  245.     return (ph_d2rpval (retval));
  246.  
  247.     return (RP_OK);
  248. }
  249. /* */
  250.  
  251. ph_wstm (buffer, len)            /* write next part of char stream     */
  252. char    buffer[];          /* chars to write                     */
  253. int       len;                      /* number of chars to write           */
  254. {
  255.     short     retval;
  256.  
  257. #ifdef DEBUG
  258.     ll_log (logptr, LLOGBTR, "ph_wstm () (%d)'%s'", len, buffer ? buffer : "");
  259. #endif
  260.  
  261. #ifdef RUNALON
  262.     retval = write (1, buffer, len);
  263.     if (retval == len)
  264.     return (RP_OK);
  265.     else
  266.     return (RP_NO);
  267. #endif
  268.  
  269.     if (buffer == 0 && len == 0)
  270.     retval = d_sneot ();     /* flush the buffer                   */
  271.     else
  272.     retval = d_snstream (buffer, len);
  273.  
  274.     if (retval < D_OK)
  275.     return (ph_d2rpval (retval));
  276.     return (RP_OK);
  277. }
  278. /* */
  279.  
  280. ph_d2rpval (retval)               /* map d_errno into rp.h value        */
  281. int       retval;
  282. {
  283. #ifdef DEBUG
  284.     ll_log (logptr, LLOGBTR, "(%d) => dial err (%d)", retval, d_errno);
  285. #endif
  286.  
  287.     switch (d_errno)
  288.     {
  289.     case D_LOGERR:           /* probably locked                    */
  290.         ll_err (logptr, LLOGTMP, "phone log");
  291.         return (RP_AGN);      /* maybe  transient problem           */
  292.  
  293.     case D_NOPORT:            /* no port or line available          */
  294.     case D_BUSY: 
  295.     case D_ABAN: 
  296.         return (RP_AGN);      /* highly transient problem           */
  297.  
  298.     case D_TIMEOUT:           /* alarm during port read/write call  */
  299.         return (RP_TIME);     /* same type of code                  */
  300.  
  301.     case D_RCVQUIT:           /* a QUIT packet has been received    */
  302.         return (RP_DONE);
  303.  
  304.     case D_PORTEOF:           /* eof on port                        */
  305.         return (RP_EOF);
  306.  
  307.     case D_NOPWR:             /* the dialer has no power            */
  308.     case D_PORTOPEN:          /* error trying to open port          */
  309.         return (RP_NET);
  310.  
  311.     case D_PORTRD:            /* error on port read                 */
  312.     case D_PORTWRT:           /* error on port write                */
  313.         return (RP_NIO);
  314.  
  315.     case D_NORESP:            /* no response to transmitted packet  */
  316.         return (RP_DHST);     /* assume the host is messed up       */
  317.  
  318.     case D_PATHERR:           /* error in path packet               */
  319.     case D_PACKERR:           /* error in packet format             */
  320.         return (RP_BHST);
  321.  
  322.     case D_TSOPEN:            /* error opening transcript file      */
  323.     case D_LOCKERR:           /* error opening/creating lock file   */
  324.         return (RP_LOCK);
  325.  
  326.     case D_CALLLOG:           /* error opening call log file        */
  327.         return (RP_FOPN);
  328.  
  329.     case D_TSWRITE:           /* error writing on transcript file   */
  330.         return (RP_FIO);
  331.  
  332.     case D_SYSERR:            /* undistinguished system error       */
  333.     case D_FORKERR:           /* couldn't fork after several tries  */
  334.     case D_PRTSGTTY:          /* error doing stty or gtty on port   */
  335.         return (RP_LIO);
  336.  
  337.     case D_SCRERR:            /* error in script file               */
  338.     case D_ACCERR:            /* error in access file               */
  339.     case D_NONUMBS:           /* no numbers given to dialer         */
  340.     case D_NOESC:             /* no esacpe character could be found */
  341.     case D_BADSPD:            /* bad speed designation              */
  342.         return (RP_PARM);
  343.  
  344.     case D_INTERR:            /* internal package error             */
  345.     case D_INITERR:           /* trouble initializing               */
  346.     case D_BADDIG:            /* bad digit passed to dialer         */
  347.         return (RP_NO);
  348.  
  349.     default:           /* punt                               */
  350.         ll_err (logptr, LLOGTMP,
  351.             "unclassified category (%d) phone error (%d)",
  352.                 retval, d_errno);
  353.         return (RP_NO);
  354.     }
  355. }
  356.